Categories
JavaScript

Good Parts of JavaScript — Currying, Memoization, and Inheritance

Spread the love

JavaScript is one of the most popular programming languages in the world. It can do a lot and have some features that are ahead of many other languages.

In this article, we’ll look at ways to curry functions, memoization, and inheritance.

Curry

Curry functions allow us to produce a new function by combining a function and an argument.

We can create a curry function to return a function that has some arguments applied and let us apply the remaining arguments by writing the following:

const curry = (fn, ...args) => {
  return (...moreArgs) => {
    return fn.apply(null, [...args, ...moreArgs]);
  };
}

In the code above, we have the curry function, which takes a function fn and some arguments args after it.

Inside it, we return a function that returns fn with all the arguments from both functions applied to it.

This way, we first apply the arguments in args , then we apply the arguments in moreArgs to fn .

Now if we call it as follows:

const add = (a, b, c) => a + b + c;

const curried = curry(add, 1);
const result = curried(2, 3);

We first get a function with 1 applied to add in curried .

Then we get the final sum by applying 2 and 3 to curried .

Therefore, result is 6.

We can improve curry by replacing apply with the spread syntax:

const curry = (fn, ...args) => {
  return (...moreArgs) => {
    return fn(...[...args, ...moreArgs]);
  };
}

This is cleaner and now fn can be arrow functions in addition to a traditional function.

Memoization

We can do memorization by keeping previously computed results that we need later.

For instance, if we have a function that computes a Fibonacci number, we can write:

const fib = (num) => {
  let a = 1,
    b = 1;
  for (let i = 1; i <= num; i++) {
    [a, b] = [b, a + b];
  }
  return a;
}

In the code above, we store the values of a and b .

We keep the values of a and b so that we can use it to create new Fibonacci numbers with them.

Inheritance

JavaScript inheritance is done by using prototypical inheritance.

However, it has a syntax that resembles classical inheritance with the class syntax.

For instance, we can implement inheritance by writing the following code:

class Animal {
  speak() {
    //...
  }
}

class Dog extends Animal {}
class Cat extends Animal {}

In the code above, we used the class keyword to create constructors.

The extends keyword is used to inherit members from Animal in the Dog and Cat constructors.

Now if we create a new Dog instance:

const dog = new Dog();

We have the __proto__ property in Dog which is set to the Animal constructor.

The speak method is in the object that’s set as the value of the __proto__ property.

We can call the speak method by writing dog.speak() .

Prototypal Inheritance

If we have object literals, we can use the Object.create method to inherit items from another object.

We can use it as follows:

const parent = {
  foo() {
    //...
  }
}

const child = Object.create(parent);
console.log(child);

In the code above, we have the parent object with the foo method.

Then we can use the Object.create method to create an object with parent as the prototype.

If we log the child object’s content, we have the __proto__ property which has the prototype of child .

The __proto__ property has the foo method.

Like inherited methods from class/constructor instances, we can call foo as follows:

child.foo();

Conclusion

We can curry functions by returning a function that applies arguments to a function that hasn’t been applied yet.

Memoization can be done by storing values that will be used later so we can use them.

For inheritance, we can create constructors with the class syntax with the extends keyword.

We can also use the Object.create method for creating objects with our own prototypes.

This is a convenient way to create objects from a prototype object and inherit its properties.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *